package com.ssy.lingxi.after.sale.serviceimpl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import com.ssy.lingxi.after.sale.entity.ReturnDeliveryGoodsDO;
import com.ssy.lingxi.after.sale.entity.ReturnDeliveryGoodsDetailDO;
import com.ssy.lingxi.after.sale.entity.ReturnGoodsDO;
import com.ssy.lingxi.after.sale.entity.ReturnGoodsDetailAssociatedDO;
import com.ssy.lingxi.after.sale.model.constant.ReturnDeliveryGoodsStatusEnum;
import com.ssy.lingxi.after.sale.model.vo.request.CommodityPageVO;
import com.ssy.lingxi.after.sale.model.vo.request.DeliveryGoodsPageVO;
import com.ssy.lingxi.after.sale.model.vo.request.ReceiveGoodsPageVO;
import com.ssy.lingxi.after.sale.model.vo.response.*;
import com.ssy.lingxi.after.sale.repository.ReturnDeliveryGoodsDetailRepository;
import com.ssy.lingxi.after.sale.repository.ReturnDeliveryGoodsRepository;
import com.ssy.lingxi.after.sale.repository.ReturnGoodsDetailMaterielRepository;
import com.ssy.lingxi.after.sale.repository.ReturnGoodsRepository;
import com.ssy.lingxi.after.sale.service.IFeignService;
import com.ssy.lingxi.after.sale.service.IReturnDeliveryGoodsService;
import com.ssy.lingxi.common.exception.BusinessException;
import com.ssy.lingxi.common.model.dto.UserLoginCacheDTO;
import com.ssy.lingxi.common.response.PageData;
import com.ssy.lingxi.common.response.ResponseCode;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.logistics.api.dto.response.LogisticsOrderFeignResponse;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.persistence.criteria.Predicate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 退货发货接口实现
 * @author 伍将
 * @date 2020/10/19
 * @version 2.0.0
 */
@Service
public class ReturnDeliveryGoodsServiceImpl implements IReturnDeliveryGoodsService {

    @Resource
    private ReturnDeliveryGoodsRepository repository;

    @Resource
    private ReturnDeliveryGoodsDetailRepository returnDeliveryGoodsDetailRepository;

    @Resource
    private ReturnGoodsRepository returnGoodsRepository;
    @Resource
    private IFeignService feignService;
    @Resource
    private ReturnGoodsDetailMaterielRepository returnGoodsDetailMaterielRepository;

    /**
     * 分页查询发货
     * @author 伍将
     * @date 2020/10/19
     * @param pageVO: 
     * @return com.ssy.lingxi.common.response.Wrapper<com.ssy.lingxi.common.response.PageData < com.ssy.lingxi.after.sale.model.vo.response.DeliveryGoodsVO>>
     **/
    @Override
    public Wrapper<PageData<DeliveryGoodsVO>> pageDeliveryGoods(UserLoginCacheDTO user, DeliveryGoodsPageVO pageVO) {

        ReturnGoodsDO returnDO = returnGoodsRepository.findById(pageVO.getDataId()).orElse(null);
        if (returnDO == null) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_NOT_EXIST);
        }
        boolean isSupplier = false;
        if (user.getMemberId().equals(returnDO.getParentMemberId()) && user.getMemberRoleId().equals(returnDO.getParentMemberRoleId())) {
            // 如果当前登录用户会员id与角色id等于供应商会员id与角色id
            isSupplier = true;
        }

        // step 1: 组装查询条件
        Specification<ReturnDeliveryGoodsDO> spec =  (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            list.add(criteriaBuilder.equal(root.get("returnId").as(Long.class), pageVO.getDataId()));
            list.add(criteriaBuilder.equal(root.get("batchNo").as(Integer.class), pageVO.getBatchNo()));
            Predicate[] p = new Predicate[list.size()];
            return criteriaBuilder.and(list.toArray(p));
        };

        // step 2: 组装分页参数
        Pageable page = PageRequest.of(pageVO.getCurrent() - 1, pageVO.getPageSize(), Sort.by("id").descending());

        // step 3: 分页查询数据
        Page<ReturnDeliveryGoodsDO> result = repository.findAll(spec, page);

        // step 4: 组装返回数据
        Boolean finalIsSupplier = isSupplier;
        List<DeliveryGoodsVO> resultList = result.getContent().stream().map(r -> {
            DeliveryGoodsVO queryVO = new DeliveryGoodsVO();
            queryVO.setDeliveryId(r.getId());
            queryVO.setBatch(r.getBatchNo());
            queryVO.setDeliveryNoId(r.getId());
            queryVO.setDeliveryNo(r.getDeliveryOrderNo());
            queryVO.setDeliveryTime(DateUtil.format(DateUtil.date(r.getDeliveryTime()), "yyyy-MM-dd HH:mm"));
            queryVO.setLogisticsName(r.getLogisticsName());
            queryVO.setLogisticsOrderNo(r.getLogisticsOrderNo());
            queryVO.setLogisticsId(r.getLogisticsId());
            queryVO.setStorageId(r.getStorageId());
            queryVO.setStorageNo(r.getStorageNo());
            queryVO.setStorageTime(DateUtil.format(DateUtil.date(r.getStorageTime()), "yyyy-MM-dd HH:mm"));
            queryVO.setInnerStatus(r.getStatus());
            queryVO.setInnerStatusName(ReturnDeliveryGoodsStatusEnum.getMessage(r.getStatus(), finalIsSupplier));
            //发货明细
            List<DeliveryGoodsDetailVO> detailList = r.getDetailList().stream().map(o -> {
                DeliveryGoodsDetailVO detail = new DeliveryGoodsDetailVO();
                detail.setOrderNo(o.getOrderNo());
                detail.setProductId(o.getProductId());
                detail.setProductName(o.getProductName());
                detail.setCategory(o.getCategory());
                detail.setBrand(o.getBrand());
                detail.setUnit(o.getUnit());
                detail.setCount(o.getReturnCount());
                detail.setDeliveryCount(o.getDeliveryCount());
                detail.setStorageCount(o.getStorageCount());
                detail.setDifferenceCount(o.getDeliveryCount() - o.getStorageCount());

                return detail;
            }).collect(Collectors.toList());
            queryVO.setDetailList(detailList);

            return queryVO;
        }).collect(Collectors.toList());

        return Wrapper.success(new PageData<>(result.getTotalElements(), resultList));
    }

    /**
     * 分页查询收货
     * @author 伍将
     * @date 2020/10/19
     * @param pageVO: 
     * @return com.ssy.lingxi.common.response.Wrapper<com.ssy.lingxi.common.response.PageData < com.ssy.lingxi.after.sale.model.vo.response.ReceiveGoodsVO>>
     **/
    @Override
    public Wrapper<PageData<ReceiveGoodsVO>> pageReceiveGoods(UserLoginCacheDTO user,ReceiveGoodsPageVO pageVO) {

        ReturnGoodsDO returnDO = returnGoodsRepository.findById(pageVO.getDataId()).orElse(null);
        if (returnDO == null) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_NOT_EXIST);
        }
        boolean isSupplier = false;
        if (user.getMemberId().equals(returnDO.getParentMemberId()) && user.getMemberRoleId().equals(returnDO.getParentMemberRoleId())) {
            // 如果当前登录用户会员id与角色id等于供应商会员id与角色id
            isSupplier = true;
        }

        // step 1: 组装查询条件
        Specification<ReturnDeliveryGoodsDO> spec =  (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            list.add(criteriaBuilder.equal(root.get("returnId").as(Long.class), pageVO.getDataId()));
            list.add(criteriaBuilder.equal(root.get("batchNo").as(Integer.class), pageVO.getBatchNo()));
            Predicate[] p = new Predicate[list.size()];
            return criteriaBuilder.and(list.toArray(p));
        };

        // step 2: 组装分页参数
        Pageable page = PageRequest.of(pageVO.getCurrent() - 1, pageVO.getPageSize(), Sort.by("id").descending());

        // step 3: 分页查询数据
        Page<ReturnDeliveryGoodsDO> result = repository.findAll(spec, page);

        // step 4: 组装返回数据
        Boolean finalIsSupplier = isSupplier;
        List<ReceiveGoodsVO> resultList = result.getContent().stream().map(r -> {
            ReceiveGoodsVO queryVO = new ReceiveGoodsVO();
            queryVO.setDeliveryId(r.getId());
            queryVO.setBatch(r.getBatchNo());
            queryVO.setDeliveryNoId(r.getId());
            queryVO.setDeliveryNo(r.getDeliveryOrderNo());
            queryVO.setDeliveryTime(DateUtil.format(DateUtil.date(r.getDeliveryTime()), "yyyy-MM-dd HH:mm"));
            queryVO.setLogisticsName(r.getLogisticsName());
            queryVO.setLogisticsOrderNo(r.getLogisticsOrderNo());
            queryVO.setStorageNo(r.getStorageNo());
            queryVO.setStorageTime(DateUtil.format(DateUtil.date(r.getStorageTime()), "yyyy-MM-dd HH:mm"));
            queryVO.setInnerStatus(r.getStatus());
            queryVO.setInnerStatusName(ReturnDeliveryGoodsStatusEnum.getMessage(r.getStatus(), finalIsSupplier));
            //发货明细
            List<ReceiveGoodsDetailVO> detailList = r.getDetailList().stream().map(o -> {
                ReceiveGoodsDetailVO detail = new ReceiveGoodsDetailVO();
                detail.setOrderNo(o.getOrderNo());
                detail.setProductId(o.getProductId());
                detail.setProductName(o.getProductName());
                detail.setCategory(o.getCategory());
                detail.setBrand(o.getBrand());
                detail.setUnit(o.getUnit());
                detail.setReturnCount(o.getReturnCount());
                detail.setDeliveryCount(o.getDeliveryCount());
                detail.setStorageCount(o.getStorageCount());
                detail.setDifferenceCount(o.getDeliveryCount() - o.getStorageCount());

                return detail;
            }).collect(Collectors.toList());
            queryVO.setDetailList(detailList);

            return queryVO;
        }).collect(Collectors.toList());

        return Wrapper.success(new PageData<>(result.getTotalElements(), resultList));
    }

    /**
     * 获取发货明细
     * @param returnId 换货id
     * @return 货明细
     */
    @Override
    public List<DeliveryGoodsVO> getDeliveryList(Long returnId, Boolean isSupplier) {
        List<ReturnDeliveryGoodsDO> result = repository.findByReturnIdOrderByBatchNo(returnId);
        //查询物流单信息
        List<Long> logisticsIds = result.stream().map(ReturnDeliveryGoodsDO::getLogisticsId).filter(Objects::nonNull).collect(Collectors.toList());
        Map<Long, LogisticsOrderFeignResponse> logisticsInfoByIds = feignService.listLogisticsOrderMap(logisticsIds);
        return result.stream().map(r -> {
            DeliveryGoodsVO queryVO = new DeliveryGoodsVO();
            queryVO.setDeliveryId(r.getId());
            queryVO.setBatch(r.getBatchNo());
            queryVO.setDeliveryNoId(r.getId());
            queryVO.setDeliveryNo(r.getDeliveryOrderNo());
            queryVO.setDeliveryTime(DateUtil.format(DateUtil.date(r.getDeliveryTime()), "yyyy-MM-dd HH:mm"));
            queryVO.setLogisticsName(r.getLogisticsName());
            queryVO.setLogisticsOrderNo(r.getLogisticsOrderNo());
            queryVO.setLogisticsId(r.getLogisticsId());
            queryVO.setStorageId(r.getStorageId());
            queryVO.setStorageNo(r.getStorageNo());
            queryVO.setStorageTime(r.getStorageTime() != null ? DateUtil.format(DateUtil.date(r.getStorageTime()), "yyyy-MM-dd HH:mm") : "");
            queryVO.setInnerStatus(r.getStatus());
            queryVO.setInnerStatusName(ReturnDeliveryGoodsStatusEnum.getMessage(r.getStatus(), isSupplier));
            //查询物流单信息
            if(r.getLogisticsId()!=null&&logisticsInfoByIds!=null){
                LogisticsOrderFeignResponse logisticsOrderData = logisticsInfoByIds.get(r.getLogisticsId());
                if(logisticsOrderData!=null) {
                    queryVO.setLogisticsReceiveAddress(logisticsOrderData.getReceiverFullAddress());
                    queryVO.setLogisticsReceiveAddressId(logisticsOrderData.getReceiverAddressId());
                    queryVO.setShipperAddressId(logisticsOrderData.getShipperAddressId());
                    queryVO.setShipperFullAddress(logisticsOrderData.getShipperFullAddress());
                }
            }
            //查询关联商品信息
            List<Long> detailIds = r.getDetailList().stream().filter(o ->o.getReturnGoodsDetailDO()!=null).map(o -> o.getReturnGoodsDetailDO().getId()).collect(Collectors.toList());
            List<ReturnGoodsDetailAssociatedDO> associatedDOList = returnGoodsDetailMaterielRepository.findAllByReturnDetailIdIn(detailIds);
            Map<Long,ReturnGoodsDetailAssociatedDO> detailMap=null;
            if(CollectionUtil.isNotEmpty(associatedDOList)){
                detailMap = associatedDOList.stream().collect(Collectors.toMap(ReturnGoodsDetailAssociatedDO::getReturnDetailId, v -> v));
            }
            //发货明细
            List<DeliveryGoodsDetailVO> detailList = new ArrayList<>();
            for(ReturnDeliveryGoodsDetailDO o:  r.getDetailList()){
                DeliveryGoodsDetailVO detail = new DeliveryGoodsDetailVO();
                detail.setOrderNo(o.getOrderNo());
                detail.setProductId(o.getProductId());
                detail.setProductName(o.getProductName());
                detail.setCategory(o.getCategory());
                detail.setBrand(o.getBrand());
                detail.setUnit(o.getUnit());
                detail.setCount(o.getReturnCount());
                detail.setDeliveryCount(o.getDeliveryCount());
                detail.setStorageCount(o.getStorageCount());
                detail.setDifferenceCount(o.getDeliveryCount() - o.getStorageCount());
                if(detailMap!=null) {
                    ReturnGoodsDetailAssociatedDO associatedDO = detailMap.get(o.getReturnGoodsDetailDO().getId());
                    if(associatedDO!=null){
                        AssociatedProductVO associatedProductVO=new AssociatedProductVO();
                        BeanUtils.copyProperties(associatedDO,associatedProductVO);
                        detail.setAssociatedProductVO(associatedProductVO);
                    }
                }
                detailList.add(detail);
            }
            queryVO.setDetailList(detailList);

            return queryVO;
        }).collect(Collectors.toList());
    }

    /**
     * 物流服务获取退货商品
     * @author 伍将
     * @date 2020/12/8
     * @param pageVO:
     * @return 取退货商品
     **/
    @Override
    public Wrapper<PageData<CommodityQueryVO>> pageCommodityByLogistics(CommodityPageVO pageVO) {

        ReturnGoodsDO returnDO = returnGoodsRepository.findById(pageVO.getDataId()).orElse(null);
        if (returnDO == null) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_NOT_EXIST);
        }

        ReturnDeliveryGoodsDO deliveryGoodsDO = repository.findByReturnIdAndBatchNo(returnDO.getId(), returnDO.getReturnBatch());
        if (deliveryGoodsDO == null) {
            throw new BusinessException(ResponseCode.AS_RETURN_DELIVERY_GOODS_NOT_EXIST);
        }

        // step 1: 组装查询条件
        Specification<ReturnDeliveryGoodsDetailDO> spec = (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            list.add(criteriaBuilder.equal(root.get("deliveryGoods").get("id").as(Long.class), deliveryGoodsDO.getId()));
            if (StringUtils.hasLength(pageVO.getBrand())) {
                list.add(criteriaBuilder.like(root.get("brand").as(String.class), "%" + pageVO.getBrand().trim() + "%"));
            }
            if (StringUtils.hasLength(pageVO.getCategory())) {
                list.add(criteriaBuilder.like(root.get("category").as(String.class), "%" + pageVO.getCategory().trim() + "%"));
            }
            if (StringUtils.hasLength(pageVO.getProductName())) {
                list.add(criteriaBuilder.like(root.get("productName").as(String.class), "%" + pageVO.getProductName().trim() + "%"));
            }
            Predicate[] p = new Predicate[list.size()];
            return criteriaBuilder.and(list.toArray(p));
        };

        // step 2: 组装分页参数
        Pageable page = PageRequest.of(pageVO.getCurrent() - 1, pageVO.getPageSize(), Sort.by("id").descending());

        // step 3: 分页查询数据
        Page<ReturnDeliveryGoodsDetailDO> result = returnDeliveryGoodsDetailRepository.findAll(spec, page);

        // step 4: 组装返回数据
        List<CommodityQueryVO> resultList = result.getContent().stream().map(r -> {
            CommodityQueryVO queryVO = new CommodityQueryVO();
            queryVO.setId(r.getId());
            queryVO.setOrderNo(r.getOrderNo());
            queryVO.setProductId(r.getProductId());
            queryVO.setProductName(r.getProductName());
            queryVO.setCategory(r.getCategory());
            queryVO.setBrand(r.getBrand());
            queryVO.setUnit(r.getUnit());
            return queryVO;
        }).collect(Collectors.toList());

        return Wrapper.success(new PageData<>(result.getTotalElements(), resultList));
    }
}
